using System.IO;
using System.Net;
using BSDS.Core.Infrastructure.TransferProgress;
using BSDS.Core.Model.Services.Uploading.DataProviders;

namespace BSDS.Core.Infrastructure.RemoteCommunication
{
    public class ServiceClient
    {
        private const int ChunkSize = 16384;

        private readonly ReportingStreamFactory streamFactory;

        public ServiceClient(ReportingStreamFactory streamFactory)
        {
            this.streamFactory = streamFactory;
        }

        public RequestResult SendRequest(string uri, string method)
        {
            var request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = method;

            return DownloadResponse(request);
        }

        public RequestResult SendRequest(string uri, IDataProvider dataProvider)
        {
            var request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = "POST";
            request.ContentType = "text/plain";
            request.ContentLength = dataProvider.DataSizeInBytes;
            request.AllowWriteStreamBuffering = false;

            using (var requestStream = request.GetRequestStream())
            using (var progressStream = streamFactory.Create(requestStream, dataProvider.DataSizeInBytes))
            {
                dataProvider.WriteTo(progressStream);
            }

            return DownloadResponse(request);
        }

        public RequestResult SendRequest(string uri, Stream data)
        {
            var request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = "POST";
            request.ContentType = "application/xml";

            var buffer = new byte[ChunkSize];

            using (var requestStream = request.GetRequestStream())
            {
                int bytesRead = data.Read(buffer, 0, buffer.Length);
                while (bytesRead > 0)
                {
                    requestStream.Write(buffer, 0, bytesRead);

                    bytesRead = data.Read(buffer, 0, buffer.Length);
                }
            }

            return DownloadResponse(request);
        }

        private static RequestResult DownloadResponse(HttpWebRequest request)
        {
            using (var response = request.GetResponse())
            using (var responseStream = response.GetResponseStream())
            {
                var httpResponse = (HttpWebResponse)response;
                var responseText = string.Empty;

                if (responseStream != null)
                {
                    using (var responseReader = new StreamReader(responseStream))
                    {
                        responseText = responseReader.ReadToEnd();
                    }
                }

                return new RequestResult(responseText, httpResponse.StatusCode);
            }
        }
    }
}